﻿using BnbjoyBackend.Site.ConstantsNS;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;

namespace BnbjoyBackend.Site.Security
{
    public class AuthorizedUserManager
    {
        private static readonly AuthorizedUserManager instance = new AuthorizedUserManager();

        private AuthorizedUserManager()
        {
        }

        public static AuthorizedUserManager Instance
        {
            get
            {
                return instance;
            }
        }

        internal string UserName { get; set; }
        public bool Store30Days { get; set; }

        public void SetTokenInfo(string userName, string accessToken, string refreshToken, bool store30Days = false)
        {
            this.UserName = userName;
            this.AccessToken = accessToken;
            this.RefreshToken = refreshToken;
            this.Store30Days = store30Days;
        }

        /// <summary>
        /// 开放接口token
        /// </summary>
        public string PublicAccessToken
        {
            get
            {
                if (HttpContext.Current.Session[Constants.PublicAccessTokenSession] != null)
                {
                    return HttpContext.Current.Session[Constants.PublicAccessTokenSession].ToString();
                }
                else
                {
                    //如果session不存在public access token，那么生成一个新的
                    var tokenResponse = TokenManager.Instance.GetPublicAccessToken();
                    if (!tokenResponse.IsError)
                        HttpContext.Current.Session[Constants.PublicAccessTokenSession] = tokenResponse.AccessToken;

                    return tokenResponse.AccessToken;
                }
            }
        }

        /// <summary>
        /// 登录用户token
        /// </summary>
        public string AccessToken
        {
            get
            {
                //如果存在access token，直接返回
                if (HttpContext.Current.Session[Constants.AccessTokenSession] != null)
                {
                    return HttpContext.Current.Session[Constants.AccessTokenSession].ToString();
                }
                else
                {
                    var atCookie = HttpContext.Current.Request.Cookies[Constants.AccessTokenCookie];
                    if (atCookie != null)
                    {
                        //读取cookie，重新写Session
                        HttpContext.Current.Session[Constants.AccessTokenSession] = atCookie.Value;
                        return atCookie.Value;
                    }
                    else
                    {
                        return string.Empty;
                    }
                }
            }

            set
            {
                var atCookie = HttpContext.Current.Request.Cookies[Constants.AccessTokenCookie];
                if (atCookie == null)
                {
                    atCookie = new HttpCookie(Constants.AccessTokenCookie);
                    atCookie.Value = value;
                    atCookie.Domain = HttpContext.Current.Request.Url.Host;
                    if (this.Store30Days)
                    {
                        atCookie.Expires = DateTime.Now.AddDays(30d);
                    }
                    else
                    {
                        atCookie.Expires = DateTime.Now.AddDays(1d);
                    }
                    HttpContext.Current.Response.Cookies.Add(atCookie);
                }
                else
                {
                    atCookie.Value = value;
                }

                HttpContext.Current.Session[Constants.AccessTokenCookie] = value;
            }
        }

        public string RefreshToken
        {
            get
            {
                if (HttpContext.Current.Session[Constants.RefreshTokenSession] != null)
                {
                    return HttpContext.Current.Session[Constants.RefreshTokenSession].ToString();
                }
                else
                {
                    var rtCookie = HttpContext.Current.Request.Cookies[Constants.RefreshTokenCookie];
                    if (rtCookie != null)
                    {
                        HttpContext.Current.Session[Constants.RefreshTokenSession] = rtCookie.Value;
                        return rtCookie.Value;
                    }
                    else
                    {
                        return string.Empty;
                    }
                }
            }

            set
            {
                var rtCookie = HttpContext.Current.Request.Cookies[Constants.RefreshTokenCookie];
                if (rtCookie == null)
                {
                    rtCookie = new HttpCookie(Constants.RefreshTokenCookie);
                    rtCookie.Value = value;
                    rtCookie.Domain = HttpContext.Current.Request.Url.Host;
                    rtCookie.Expires = DateTime.Now.AddDays(2d); //默认2天
                    HttpContext.Current.Response.Cookies.Add(rtCookie);
                }
                else
                {
                    rtCookie.Value = value;
                }

                HttpContext.Current.Session[Constants.RefreshTokenSession] = value;
            }
        }

        public bool UserLoggedIn
        {
            get
            {
                return !string.IsNullOrWhiteSpace(this.AccessToken) &&
                       !string.IsNullOrWhiteSpace(this.RefreshToken);
            }
        }

        /// <summary>
        /// 获取当前用户正在访问的民宿信息 - 同步方法供filter attribute使用
        /// </summary>
        /// <returns></returns>
        public dynamic GetCurrentBnbInfoSync()
        {
            if (HttpContext.Current.Session[Constants.OnDomainBnbsSession] != null)
            {
                return HttpContext.Current.Session[Constants.OnDomainBnbsSession] as dynamic;
            }
            else
            {
                try
                {
                    HttpPostResponse response = ServiceManager.Instance.PostServiceSync(this.AccessToken, "account/managedbnbs", "");
                    if (response.StatusCode == HttpStatusCode.OK && response.Content.Length > 0)
                    {
                        List<dynamic> bnbs = JsonConvert.DeserializeObject<List<dynamic>>(response.Content);
                        if (bnbs != null)
                        {
                            return bnbs;
                        }
                    }
                    else if (response.StatusCode == HttpStatusCode.Redirect)
                    {
                        return response;
                    }

                    return null;

                }
                catch (Exception ex)
                {
                    return null;
                }
            }
        }

        /// <summary>
        /// 获取当前用户正在访问的民宿信息
        /// </summary>
        /// <returns></returns>
        public async Task<dynamic> GetCurrentBnbInfo()
        {
            if (HttpContext.Current.Session[Constants.OnDomainBnbsSession] != null)
            {
                return HttpContext.Current.Session[Constants.OnDomainBnbsSession] as dynamic;
            }
            else
            {
                try
                {
                    HttpPostResponse response = await ServiceManager.Instance.PostService(this.AccessToken, "account/managedbnbs", "");
                    if (response.StatusCode == HttpStatusCode.OK && response.Content.Length > 0)
                    {
                        List<dynamic> bnbs = JsonConvert.DeserializeObject<List<dynamic>>(response.Content);
                        if (bnbs != null)
                        {
                            return bnbs;
                        }
                    }
                    else if (response.StatusCode == HttpStatusCode.Redirect)
                    {
                        return response;
                    }

                    return null;

                }
                catch (Exception ex)
                {
                    return null;
                }
            }
        }

        /// <summary>
        /// 因filter attibute中使用异步task会有死锁问题，故需要同步的一份copy
        /// </summary>
        /// <returns></returns>
        public dynamic GetUserInfoSync(string userId, string role, string bnbId)
        {
            if (HttpContext.Current.Session[Constants.AuthedUserInfo] != null)
            {
                return HttpContext.Current.Session[Constants.AuthedUserInfo] as dynamic;
            }
            else
            {
                try
                {
                    dynamic paramObj = new ExpandoObject();
                    paramObj.userId = userId;
                    paramObj.role = role;
                    paramObj.bnbId = bnbId;
                    string paramObjJson = JsonConvert.SerializeObject(paramObj);

                    HttpPostResponse response = ServiceManager.Instance.PostServiceSync(this.AccessToken, "account/user_with_bnbpermission_info", paramObjJson);
                    if (response.StatusCode == HttpStatusCode.OK && response.Content.Length > 0)
                    {
                        dynamic resObj = (JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(response.Content);
                        if (resObj != null)
                        {
                            Dictionary<string, string> authDic = new Dictionary<string, string>();
                            string[] authKeys = Constants.AuthKeys.Split(',');
                            string[] authUrls = Constants.AuthUrls.Split(',');

                            if (resObj.permission == "*")
                            {
                                for (int i = 0; i < authKeys.Count(); i++)
                                {
                                    authDic.Add(authKeys[i], authUrls[i]);
                                }
                            }
                            else
                            {
                                string[] permissionArr = resObj.permission.split(',');
                                foreach (var p in permissionArr)
                                {
                                    int index = int.Parse(p) - 1;
                                    authDic.Add(authKeys[index], authUrls[index]);
                                }
                            }

                            resObj.AuthMap = JObject.FromObject(authDic);
                            //将用户基本信息写入Session
                            HttpContext.Current.Session[Constants.AuthedUserInfo] = resObj;
                            return resObj;
                        }
                    }
                    else if (response.StatusCode == HttpStatusCode.Redirect)
                    {
                        return response;
                    }

                    return null;
                }
                catch (Exception ex)
                {
                    return null;
                }

            }
        }

        /// <summary>
        /// 获取用户基本信息，可能返回文本，也可能返回跳转信息
        /// </summary>
        /// <returns></returns>
        public async Task<dynamic> GetUserInfo(string userId, string role, string bnbId)
        {
            if (HttpContext.Current.Session[Constants.AuthedUserInfo] != null)
            {
                return HttpContext.Current.Session[Constants.AuthedUserInfo] as dynamic;
            }
            else
            {
                try
                {
                    dynamic paramObj = new ExpandoObject();
                    paramObj.userId = userId;
                    paramObj.role = role;
                    paramObj.bnbId = bnbId;
                    string paramObjJson = JsonConvert.SerializeObject(paramObj);

                    HttpPostResponse response = await ServiceManager.Instance.PostService(this.AccessToken, "account/user_with_bnbpermission_info", paramObjJson);
                    if (response.StatusCode == HttpStatusCode.OK && response.Content.Length > 0)
                    {
                        dynamic resObj = (JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(response.Content);
                        if (resObj != null)
                        {
                            Dictionary<string, string> authDic = new Dictionary<string, string>();
                            string[] authKeys = Constants.AuthKeys.Split(',');
                            string[] authUrls = Constants.AuthUrls.Split(',');

                            if (resObj.permission == "*")
                            {
                                for (int i = 0; i < authKeys.Count(); i++)
                                {
                                    authDic.Add(authKeys[i], authUrls[i]);
                                }
                            }
                            else
                            {
                                string[] permissionArr = resObj.permission.split(',');
                                foreach (var p in permissionArr)
                                {
                                    int index = int.Parse(p) - 1;
                                    authDic.Add(authKeys[index], authUrls[index]);
                                }
                            }

                            resObj.AuthMap = JObject.FromObject(authDic);
                            //将用户基本信息写入Session
                            HttpContext.Current.Session[Constants.AuthedUserInfo] = resObj;
                            return resObj;
                        }
                    }
                    else if (response.StatusCode == HttpStatusCode.Redirect)
                    {
                        return response;
                    }

                    return null;
                }
                catch (Exception ex)
                {
                    return null;
                }

            }
        }

        public void CleanTokenAndSession()
        {
            //移除Access Token Cookie
            HttpContext.Current.Session[Constants.AccessTokenSession] = null;
            RemoveCookie(Constants.AccessTokenCookie);

            //移除Refresh Token Cookie
            HttpContext.Current.Session[Constants.RefreshTokenSession] = null;
            RemoveCookie(Constants.RefreshTokenCookie);

            HttpContext.Current.Session[Constants.AuthedUserInfo] = null;
            HttpContext.Current.Session[Constants.OnDomainBnbsSession] = null;
            HttpContext.Current.Session[Constants.OnSelectBnbSession] = null;
            HttpContext.Current.Session[Constants.DashboardHeadInfo] = null;
        }

        private void RemoveCookie(string name)
        {
            if (HttpContext.Current.Request.Cookies[name] != null)
            {
                var targetCookie = new HttpCookie(name);
                targetCookie.Expires = DateTime.Now.AddDays(-1);
                HttpContext.Current.Response.Cookies.Add(targetCookie);
            }
        }

    }
}